package com.gzx.plugin.tjzy.modular.file.service.impl;

import cn.hutool.core.util.URLUtil;
import com.aliyun.oss.ServiceException;
import com.amazonaws.AmazonServiceException;
import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.model.*;
import com.gzx.plugin.tjzy.modular.file.service.FileService;
import jakarta.servlet.ServletOutputStream;
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import vip.xiaonuo.common.exception.CommonException;
import vip.xiaonuo.common.util.CommonDateUtil;

import java.io.*;
import java.util.List;

/**
 * @author zjt
 * @description
 * @date 2024/10/18 15:11
 */
@Slf4j
@RequiredArgsConstructor
@Service
public class FileServiceImpl implements FileService {

    private final AmazonS3 amazonS3;

    @Value("${jd.oss.bucket-name}")
    private String bucketNameA;


    /**
     * 创建存储桶
     */
    @Override
    public void createBucket(String bucketName) {
        amazonS3.createBucket(bucketName);
    }

    /**
     * 获取桶列表
     *
     * @return
     */
    @Override
    public List<Bucket> getBucketList() {
        return amazonS3.listBuckets();
    }

    /**
     * 上传文件
     *
     * @param file
     * @return
     * @throws IOException
     */
    @Override
    public String upload(MultipartFile file) throws IOException {
        //获取输入流
        InputStream inputStream = file.getInputStream();
        ObjectMetadata objectMetadata = new ObjectMetadata();
        objectMetadata.setContentType("image/jpeg");
        objectMetadata.setContentLength(file.getSize());
        String[] parts = file.getOriginalFilename().split("\\.");
        if (parts.length <= 1) {
            throw new ServiceException("文件上传失败");
        }
        String fileName = parts[0] + CommonDateUtil.getMillisecondTime() + "." + parts[1];
        try {
            amazonS3.putObject(bucketNameA, fileName, inputStream, objectMetadata);
            log.info("文件上传成功:{}，to:{}", fileName, bucketNameA);
            return fileName;
        } catch (AmazonServiceException e) {
            log.error(e.getMessage(), e);
            return null;
        }
    }

    /**
     * 文件上传
     *
     * @param bucketName    上传的桶的名称
     * @param multipartFile 文件
     * @return
     */
    @Override
    public String upload(String bucketName, MultipartFile multipartFile, boolean withTimestamp) throws IOException {
        //获取输入流
        InputStream inputStream = multipartFile.getInputStream();
        ObjectMetadata objectMetadata = new ObjectMetadata();
        objectMetadata.setContentType("image/jpeg");
        objectMetadata.setContentLength(multipartFile.getSize());
        String[] parts = multipartFile.getOriginalFilename().split("\\.");
        if (parts.length <= 1) {
            throw new ServiceException("文件上传失败");
        }
        String fileName = multipartFile.getOriginalFilename();
        try {
            if (withTimestamp) {
                fileName = parts[0] + CommonDateUtil.getMillisecondTime() + "." + parts[1];
            }
            amazonS3.putObject(bucketName, fileName, inputStream, objectMetadata);
            log.info("文件上传成功:{}，to:{}", fileName, bucketName);
            return fileName;
        } catch (AmazonServiceException e) {
            log.error(e.getMessage(), e);
            return null;
        }
    }

    @Override
    public void deleteFile(String name) {
        try {
            amazonS3.deleteObject(bucketNameA, name);
            log.info("文件删除成功:{}，from:{}", name, bucketNameA);
        } catch (AmazonServiceException e) {
            log.error(e.getMessage(), e);
            throw new CommonException("文件删除失败：{}", name);
        }
    }

    /**
     * 删除文件
     *
     * @param bucketName
     * @param fileName
     */
    @Override
    public void delete(String bucketName, String fileName) {
        try {
            amazonS3.deleteObject(bucketName, fileName);
            log.info("文件删除成功:{}，from:{}", fileName, bucketName);
        } catch (AmazonServiceException e) {
            log.error(e.getMessage(), e);
            throw new CommonException("文件删除失败：{}", fileName);
        }
    }

    /**
     * 下载
     *
     * @param fileName
     * @throws IOException
     */
    @Override
    public void download(String fileName, HttpServletResponse response) {
        try (S3Object o = amazonS3.getObject(bucketNameA, fileName);
             S3ObjectInputStream s3is = o.getObjectContent();
             ServletOutputStream outputStream = response.getOutputStream()) {
            response.setHeader("Content-Disposition", "attachment;filename=" + URLUtil.encode(fileName));
            response.setHeader("Access-Control-Allow-Origin", "*");
            response.setHeader("Access-Control-Expose-Headers", "Content-Disposition");
            response.setContentType("application/octet-stream;charset=UTF-8");
            // 设置响应头
            response.setContentLengthLong(o.getObjectMetadata().getContentLength());
            byte[] buffer = new byte[8192];
            int bytesRead;
            while ((bytesRead = s3is.read(buffer)) != -1) {
                outputStream.write(buffer, 0, bytesRead);
            }
            outputStream.flush();
            log.info("SUCCESS");
        } catch (AmazonS3Exception e) {
            if ("NoSuchKey".equals(e.getErrorCode())) {
                response.setStatus(HttpServletResponse.SC_NOT_FOUND);
            } else {
                response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
            }
            log.error("AmazonS3Exception occurred: ", e);
        } catch (AmazonServiceException e) {
            response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
            log.error("AmazonServiceException occurred: ", e);
        } catch (IOException e) {
            response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
            log.error("IOException occurred: ", e);
        }
    }

    /**
     * 下载
     *
     * @param bucketName
     * @param fileName
     * @param response
     * @throws IOException
     */
    @Override
    public void downloadWithBucket(String bucketName, String fileName, HttpServletResponse response) {
        try (S3Object o = amazonS3.getObject(bucketName, fileName);
             S3ObjectInputStream s3is = o.getObjectContent();
             ServletOutputStream outputStream = response.getOutputStream()) {
            response.setHeader("Content-Disposition", "attachment;filename=" + URLUtil.encode(fileName));
            response.setHeader("Access-Control-Allow-Origin", "*");
            response.setHeader("Access-Control-Expose-Headers", "Content-Disposition");
            response.setContentType("application/octet-stream;charset=UTF-8");
            // 设置响应头
            response.setContentLengthLong(o.getObjectMetadata().getContentLength());
            byte[] buffer = new byte[8192];
            int bytesRead;
            while ((bytesRead = s3is.read(buffer)) != -1) {
                outputStream.write(buffer, 0, bytesRead);
            }
            outputStream.flush();
            log.info("SUCCESS");
        } catch (AmazonS3Exception e) {
            if ("NoSuchKey".equals(e.getErrorCode())) {
                response.setStatus(HttpServletResponse.SC_NOT_FOUND);
            } else {
                response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
            }
            log.error("AmazonS3Exception occurred: ", e);
        } catch (AmazonServiceException e) {
            response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
            log.error("AmazonServiceException occurred: ", e);
        } catch (IOException e) {
            response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
            log.error("IOException occurred: ", e);
        }
    }

    @Override
    public File download(String bucketName, String fileName) throws IOException {
        try {
            // 创建临时文件
            File tempFile = File.createTempFile("download-", ".tmp");
            tempFile.deleteOnExit();
            try (S3Object o = amazonS3.getObject(bucketName, fileName);
                 S3ObjectInputStream s3is = o.getObjectContent();
                 FileOutputStream fos = new FileOutputStream(tempFile)) {
                byte[] buffer = new byte[8192];
                int bytesRead;
                while ((bytesRead = s3is.read(buffer)) != -1) {
                    fos.write(buffer, 0, bytesRead);
                }
                fos.flush();
                return tempFile;
            }
        } catch (AmazonS3Exception e) {
            log.error("文件读取出现异常", e);
            if ("NoSuchKey".equals(e.getErrorCode())) {
                throw new FileNotFoundException("File not found: " + fileName);
            }
            throw new IOException("Amazon S3 error occurred", e);
        } catch (AmazonServiceException e) {
            log.error("文件读取出现异常", e);
            throw new IOException("Amazon service error occurred", e);
        }
    }

    /**
     * 上传文件不带有时间后缀
     *
     * @param file
     * @return
     * @throws IOException
     */
    @Override
    public String uploadNoTimeSuffix(MultipartFile file) throws IOException {
        //获取输入流
        InputStream inputStream = file.getInputStream();
        ObjectMetadata objectMetadata = new ObjectMetadata();
        objectMetadata.setContentType("image/jpeg");
        objectMetadata.setContentLength(file.getSize());
        String fileName = file.getOriginalFilename();
        try {
            amazonS3.putObject(bucketNameA, fileName, inputStream, objectMetadata);
            log.info("文件上传成功:{}，to:{}", fileName, bucketNameA);
        } catch (AmazonServiceException e) {
            e.printStackTrace();
        }
        return fileName;
    }
}
